﻿using System;
using System.IO;
using System.IO.Ports;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

class GlobalVar
{



    private static string p_lograwfile_processed_path = @"C:\vexredus\vexredus-log-raw-cropped-timestamped_for_playback.txt";
    public static string lograwfile_processed_path { get { return p_lograwfile_processed_path; } set { p_lograwfile_processed_path = value; } }

    private static string p_lograwfile_time_begin = @"C:\vexredus\control_time_begin.txt";
    public static string lograwfile_time_begin { get { return p_lograwfile_time_begin; } set { p_lograwfile_time_begin = value; } }

    private static string p_lograwfile_path = @"C:\vexredus\vexredus-log-raw.txt";
    public static string lograwfile_path { get { return p_lograwfile_path; } set { p_lograwfile_path = value; } }

    private static string p_uploadfile_path = @"C:\vexredus\vexredus-log-upload.txt";
    public static string uploadfile_path { get { return p_uploadfile_path; } set { p_uploadfile_path = value; } }


    private static string p_telin_buffer = "";
    public static string telin_buffer { get { return p_telin_buffer; } set { p_telin_buffer = value; } }



}


class PortDataReceived
{

    public static void Main()
    {
        double time_scaler = 1;
        string control_time_scaler_line = "";
        double time_elapsed_at_scaler_set = 0;
        double time_begin = 0;
        bool time_begin_reached = false;
        string control_time_begin_line = "";
        
        //string recvBuffer = "";
        //string[] msgList;
        string msg = "";


        Console.WriteLine("Reading from file: " + GlobalVar.lograwfile_processed_path);
        Console.WriteLine("Press ENTER to start SIM");
        Console.ReadLine();



        // OUTGOING UDP
        UdpClient u_out = new UdpClient();


        var heartbeat_timer = new Stopwatch();
        heartbeat_timer.Start();

        var sim_timer = new Stopwatch();
        sim_timer.Start();

        int line_counter = 0;
        string line;
        double timer_diff = -1;
        double sim_timer_currentsec = 0;
        double line_time = 0;
        bool end_of_file = false;
        



        System.IO.StreamReader file_logfile_processed = new System.IO.StreamReader(GlobalVar.lograwfile_processed_path);

        while (!end_of_file)
        {
            //read control file. if any changes to it take new values and restart sim with these.
            System.IO.StreamReader file_control_time_begin = new System.IO.StreamReader(GlobalVar.lograwfile_time_begin);
            if ((control_time_begin_line = file_control_time_begin.ReadLine()) != null) //first line in control file = begin time
            {
                if ((control_time_scaler_line = file_control_time_begin.ReadLine()) != null) //second line in control file = time scaler value
                {
                    
                    if (Convert.ToDouble(control_time_begin_line) != time_begin)
                    {
                        time_begin = Convert.ToDouble(control_time_begin_line);
                        Console.WriteLine("DEBUG: time begin read: " + time_begin);
                        //Console.ReadLine();
                        sim_timer_currentsec = time_begin; //just in case of needed for time_scaler time_begin
                        sim_timer.Restart();
                        time_begin_reached = false;
                        file_logfile_processed.Close();
                        file_logfile_processed = new StreamReader(GlobalVar.lograwfile_processed_path);
                        
                        //file_logfile_processed.BaseStream.Position = 0;
                    }
                    
                    if (Convert.ToDouble(control_time_scaler_line) != time_scaler)
                    {
                        time_scaler = Convert.ToDouble(control_time_scaler_line);
                        Console.WriteLine("DEBUG: time scaler read: " + time_scaler);
                        //Console.ReadLine();
                        time_elapsed_at_scaler_set = sim_timer_currentsec - time_begin;
                        sim_timer.Restart();
                        Console.WriteLine(time_elapsed_at_scaler_set);
                        //Console.ReadLine();
                        //time_begin_reached = false;
                        //file_logfile_processed.Close();
                        //file_logfile_processed = new StreamReader(GlobalVar.lograwfile_processed_path);
                        //time_scaler_new_set = true;
                    }
                }
            }           
            file_control_time_begin.Close();


            if ((line = file_logfile_processed.ReadLine()) != null)
            {
                Console.WriteLine("");
                Console.WriteLine("###############");
                Console.Write("Current read line: ");
                Console.WriteLine(line);
                line_counter++;

                string[] line_split = line.Split(',');
                string line_msg = line.Substring(line.IndexOf(',') + 1);
                line_time = (Convert.ToDouble(line_split[0], System.Globalization.CultureInfo.InvariantCulture));
                //Console.WriteLine("#######DEBUG##############");
                //Console.WriteLine(line_split[0]);
                //Console.WriteLine(line_time);
                //Console.WriteLine(line_msg);
                //Console.WriteLine(sim_timer_currentsec);
                //Console.WriteLine(timer_diff);
                //Console.WriteLine("#####################");


                string indata = line_msg;

                Console.WriteLine("Begin waiting until line_time: " + line_time);
                while (timer_diff < 0.0)
                {
                    sim_timer_currentsec = ((sim_timer.ElapsedMilliseconds / 1000.0) * time_scaler) + time_begin + time_elapsed_at_scaler_set;
                    //Console.WriteLine("currentsec: " + sim_timer_currentsec);
                    timer_diff = sim_timer_currentsec - line_time;
                    if (line_time > time_begin) time_begin_reached = true;
                    //Console.WriteLine("current timer_diff: " + timer_diff);
                    Console.Write(".");
                    if (time_begin_reached == true) Thread.Sleep(10);
                }
                timer_diff = -1;
                Console.WriteLine("End Waiting");

                msg = indata + '\n';

                if (time_begin_reached)
                {

                    try
                    {
                        // Send to UDP
                        // Always try to open new connection (continous reconnect).
                        u_out.Connect("localhost", 65001);
                        u_out.Send(ASCIIEncoding.UTF32.GetBytes(msg), ASCIIEncoding.UTF32.GetByteCount(msg));
                        Console.Write("Current UDP msg: ");
                        Console.WriteLine(msg);
                    }
                    catch (SocketException e)
                    {
                        // Do nothing
                        Console.WriteLine("DEBUG: " + e.ToString().Split('\n')[0]);
                    }
                    //u_out.Close();
                    Thread.Sleep(10);

                }

                /*
                
                recvBuffer += indata;

                // Split into messages, for UDP flow control
                while (flow_control_loop_finished)
                {

                    if (recvBuffer.IndexOf('\n') > 0)
                    {
                        msgList = recvBuffer.Split('\n');
                        for (int i = 0; i < msgList.Length - 1; i++)
                        {
                            msg = msgList[i] + '\n';
                            //Console.WriteLine("DEBUG: msg: \"" + msg + '"');
                            try
                            {
                                // Send to UDP
                                // Always try to open new connection (continous reconnect).
                                u_out.Connect("localhost", 65001);
                                u_out.Send(ASCIIEncoding.UTF32.GetBytes(msg), ASCIIEncoding.UTF32.GetByteCount(msg));
                                Console.Write("Current UDP msg: ");
                                Console.WriteLine(msg);
                            }
                            catch (SocketException e)
                            {
                                // Do nothing
                                Console.WriteLine("DEBUG: " + e.ToString().Split('\n')[0]);
                            }
                            //u_out.Close();
                            Thread.Sleep(10); // Actual flow control: 10ms delay between messages
                        }
                        recvBuffer = recvBuffer.Substring(recvBuffer.IndexOf('\n') + 1);
                    }
                }
                */
            }
            else
            {
                Console.WriteLine("End of logfile reached! ENTER to restart");
                Console.ReadLine();
                sim_timer_currentsec = time_begin; //just in case of needed for time_scaler time_begin
                sim_timer.Restart();
                time_begin_reached = false;
                file_logfile_processed.Close();
                file_logfile_processed = new StreamReader(GlobalVar.lograwfile_processed_path);


                //end_of_file = true;
                //Console.WriteLine("DEBUG: End of line = true");
            }

        }

        file_logfile_processed.Close();
        Console.WriteLine("SIM finished!");
        Console.ReadLine();
        time_begin = 0;
    }
}